package cards;

import java.util.*;

public class Deck{
	
	private ArrayList<Card> myCardList;
	
	//Deck is instantiated as if it were a sealed deck of cards
	public Deck(){
		myCardList = new ArrayList<Card>(52);
		
		for(int suit = ICard.SPADES; suit <= ICard.CLUBS; suit++){
			for (int rank = 2; rank <= 14; rank++){
				myCardList.add(new Card(suit,rank));
			}
		}
	}
	
	//Deck can also be an arbitrary collection of cards
	//like a hand or discard pile
	public Deck(int size){
		myCardList = new ArrayList<Card>(size);
	}
	
	//accounts for the fact that players would perform
	//the shuffle operation a variable number of times
	//Anecdotally between 3 and 9
	public void shuffler(){
		Random r = new Random();
		int times = (int)(r.nextGaussian() * 2 + 7);
		
		for(int i = 0; i < times; i++){
			shuffle();
		}
		
	}
	
	//Perform one iteration of a shuffle
	//Modeled after actual shuffling results data
	private void shuffle(){
		Random r = new Random();
		ArrayList<Card> shuffledDeck = new ArrayList<Card>();
		
		//Assuming a right hand shuffler... they take the split part of deck in right hand
		//Need to figure out which cards drop first (right or left... assume dominant hand for now
		
		int lDeckIndex = 0;
		int bPoint = (int) (r.nextGaussian() * 2.88 + 26.57);				//where the deck gets "cut"
		int rDeckIndex = bPoint;
		
		int deal;
		
		while((lDeckIndex != bPoint) || (rDeckIndex != 52)){

			if(rDeckIndex <= 51){											//more cards to deal from right hand
				deal = (int) (r.nextGaussian() * 1.2 + 2);					//Randomize how many come out
				if (deal < 1) deal = 1;
				
				if(deal + rDeckIndex > 51)									//Not Enough Cards
					deal = 52 - rDeckIndex;						
					
				for(int i = deal; i > 0; i--, rDeckIndex++){				
					shuffledDeck.add(myCardList.get(rDeckIndex));				//Write Cards
				}
			}
			
			if(lDeckIndex < bPoint){
				deal = (int) (r.nextGaussian() * 1.2 + 2);					//Randomize how many come out
				if (deal < 1) deal = 1;
				
				if(deal + lDeckIndex > bPoint)								//Not Enough Cards
					deal = bPoint - lDeckIndex;								//Deal remainder
				
				
				for(int i = deal; i > 0; i--, lDeckIndex++){				
					shuffledDeck.add(myCardList.get(lDeckIndex));				//Write Cards
				}		
			}
		
		}
	
		myCardList = shuffledDeck;
		
	}
	
	//puts the Deck in rank/suit order
	//uses a variation on the insertion sort
	public void sort(){

		Collections.sort(myCardList);
	
	}
	
	
		
	//if there is another card then the write index
	//will be >0
	public boolean hasNext() {
		return myCardList.size() > 0;
	}

	
	//deal the top card from the deck
	public Card deal(){
		
		Card c;
		c = myCardList.get(lastCardIndex());
		
		myCardList.remove(c);
		
		return c;
		
	}
	
	//play an arbitrary card from the deck
	//removes the card
	public Card play(int x){
		
		//1. push card at x
		Card c;
		c = myCardList.get(x);
		
		//2. remove card from deck
		myCardList.remove(c);
		
		return c;
		
	}
	
	//look at an arbitrary card in the deck
	//does not remove the card
	public Card peek(int x){

		return myCardList.get(x);
		
	}

	public void add(Card c){
		myCardList.add(c);
	}
	
	//return number of elements in deck
	public int length(){
		return myCardList.size();
	}

	//index of last card in deck
	public int lastCardIndex(){
		
		return myCardList.size() - 1;
		
	}
	
	//print the deck to the standard output
	public void outputDeck(){
		
		for(int i = 0; i < myCardList.size(); i++){
			System.out.println(i + " : " + myCardList.get(i));
		}
	}
	
	public ArrayList<Card> getDeck(){
		return myCardList;
	}

}

